#include "CBufferObject.h"
#include <assert.h>
#include "ILDXException.h"

ldx::render::CBufferObject::CBufferObject(SDeviceMap dm,
	D3D11_USAGE usage, uint byteWidth, D3D11_BIND_FLAG bindFlags, 
	uint cpuAssessFlags, void * initData)
	:BufferObj(nullptr)
{
	HRESULT hr = 0;
	DM = dm;
	BufferType = bindFlags;
	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = usage;
	bd.ByteWidth = byteWidth;
	bd.BindFlags = bindFlags;
	bd.CPUAccessFlags = 0;
	if (!initData)
	{
		hr = DM.Window.D3DDevice->CreateBuffer(&bd, NULL, &BufferObj);
	}
	else
	{
		D3D11_SUBRESOURCE_DATA InitData;
		ZeroMemory(&InitData, sizeof(InitData));
		InitData.pSysMem = initData;
		hr = DM.Window.D3DDevice->CreateBuffer(&bd, &InitData, &BufferObj);
	}
	if (FAILED(hr))
	{
		throw os::ILDXException(L"CBufferObject D3DDevice->CreateBuffer failed!");
	}
	assert(BufferObj != nullptr);
}

ldx::render::CBufferObject::~CBufferObject()
{
	clearBuffer();
}

void ldx::render::CBufferObject::setVertexBuffers(uint startSlot , uint numBuffers, uint * pstrides , uint * offset )
{
	assert(BufferObj != nullptr);
	DM.Window.D3DDeviceContext->IASetVertexBuffers(startSlot, numBuffers, &BufferObj, pstrides, offset);
}

void ldx::render::CBufferObject::setIndexBuffer(DXGI_FORMAT format, uint offset,E_INDICE_PRIMITIVE_TYPE type)
{
	// Set index buffer
	assert(BufferObj != nullptr);
	DM.Window.D3DDeviceContext->IASetIndexBuffer(BufferObj, format, offset);
	DM.Window.D3DDeviceContext->IASetPrimitiveTopology((D3D11_PRIMITIVE_TOPOLOGY)type);
}

bool ldx::render::CBufferObject::updateSubBuffer(void * buffer, uint dstSubresource, uint srcRowPithc, uint srcDepthPitch)
{
	// Set index buffer
	assert(BufferObj != nullptr);
	DM.Window.D3DDeviceContext->UpdateSubresource(BufferObj, dstSubresource, NULL, buffer, srcRowPithc, srcDepthPitch);
	return true;
}

void ldx::render::CBufferObject::setDebugName(std::string name)
{
#ifdef _DEBUG
	if (BufferObj)
		BufferObj->SetPrivateData(WKPDID_D3DDebugObjectName, lstrlenA(name.c_str()), name.c_str());
#endif
}

void ldx::render::CBufferObject::clearBuffer()
{
	if (BufferObj)
		BufferObj->Release();
}
